﻿#pragma once
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <istream>
using namespace std;

const int rwordnum = 9;
const int nummaxlen = 9;
const int txmax = 100;
const int errormax = 100;
const int pcodemax = 1000;
const int datamaxn = 1000;

// 符号
enum symbol {
    nulsym,                     // 空
    identsym,                   // 标识符
    ifsym,                      // if
    switchsym,                  // switch
    casesym,                    // case
    forsym,                     // for
    whilesym,                   // while
    intsym,                     // int
    readsym,                    // read
    writesym,                   // write
    numbersym,                  // 数字
    plussym,                    // +
    minussym,                   // -
    mulsym,                     // *
    divsym,                     // /
    lparensym,                  // (
    rparensym,                  // )
    semicolonsym,               // ;
    geqsym,                     // >=
    leqsym,                     // <=
    neqsym,                     // !=
    eqlsym,                     // ==
    becomesym,                  // =
    gtsym,                      // >
    ltsym,                      // <
    beginsym,                   // {
    endsym,                     // }
    commasym,                   // ,
    modsym,                     // %
    constsym,                   // const
    returnsym,                  // return
};

// 符号表中的类型
enum object {
    constant,
    variable,
    procedure,
};

// 虚拟机指令类型
enum fct {
    INT,                        // 在栈顶开辟a个空间
    JMP,                        // 跳转到a
    JPC,                        // 栈顶为0跳转到a
    LIT,                        // 将常量a放到栈顶
    LOD,                        // 将地址a的变量值放到栈顶
    STO,                        // 将栈顶元素放到地址a
    CAL,                        // 函数调用
    STP,                        // 将栈顶的a个元素向上移动两格 同时当前栈顶向下移动a格    

    OPR,                        // 0 函数返回
    // 1 %
    // 2 +
    // 3 -
    // 4 *
    // 5 /
    // 6 ==   
    // 7 !=
    // 8 <
    // 9 <=
    // 10 >
    // 11 >=   
    // 12 读  
    // 13 写      
    // 14 将栈顶元素pop
    // 15 拷贝栈顶元素至栈顶
};

// 虚拟机指令结构
struct instruction {
    fct kind;
    int a;
};


// 符号表结构
struct tablestruct {
    string name;	                            // 名字
    object kind;	                            // 类型 const var procedure
    int val;                                    // 数值 仅const使用
    int adr;                                    // 地址 仅const不使用
    int par;                                    // 参数数量 仅procedure使用
    int lvar;                                   // 局部变量 仅procedure使用
    string proname;                             // 所属函数 仅var使用
};


void init();
void getch();
void getsym();
int compiler();
void constdeclaration();
void error(int errorid);
bool isvaliddeclaration(object kind);
void enter(object kind);
void renter();
void proceduredeclaration();
void parameterdeclaration();
void intdeclaration();
void block();
void statement();
void gen(fct kind, int a);
int findintable(string name);
void expression();
void term();
void factor();
void condition();
vector<instruction> GetPCode();
vector<string> GetEMS();
vector<string> GetTable();